package im.oen.boot.common.utils;

import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * 同步的数据容器
 *
 * @author Kevin.Xu
 */
public class SyncContainer<T> {

    private final CountDownLatch latch;

    public SyncContainer() {
        latch = new CountDownLatch(1);
    }

    public SyncContainer(T defaultValue) {
        this.data = defaultValue;
        latch = new CountDownLatch(1);
    }

    private T data;

    private Exception exception;

    public Optional<T> safeGetOptional() {
        try {
            latch.await();
        } catch (Exception e) {
        }
        return Optional.ofNullable(data);
    }

    public T safeGet() {
        try {
            latch.await();
        } catch (Exception e) {
        }
        return data;
    }

    public T safeGetOrThrow() throws Exception {
        try {
            latch.await();
        } catch (Exception e) {
        }

        if (exception != null) {
            throw exception;
        }
        return data;
    }

    public T get() throws InterruptedException {
        latch.await();
        return data;
    }

    public T get(long timeout, TimeUnit unit) throws InterruptedException {
        latch.await(timeout, unit);
        return data;
    }

    public synchronized void set(T data) {
        this.data = data;
        latch.countDown();
    }

    public synchronized void finish() {
        latch.countDown();
    }

    public synchronized void error(Exception exception) {
        this.exception = exception;
        latch.countDown();
    }
}
